﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MatrixGame
{
	public class Field
	{
		#region Events

		public event EventHandler<FieldClickedEventArgs> FieldClicked;

		#endregion

		private bool[,] field;

		private int mSize;
		public int Size
		{
			get
			{
				return mSize;
			}
			set
			{
				mSize = value;
				InitField();
			}
		}

		#region ctor

		public Field()
			: this(10)
		{

		}

		public Field(int size)
		{
			Size = size;
		}

		public Field(Field cloneFrom)
		{
			mSize = cloneFrom.Size;
			field = (bool[,]) cloneFrom.field.Clone();
		}

		#endregion

		#region indexer

		public bool this[int row, int column]
		{
			get { return field[row, column]; }
			set { field[row, column] = value; }
		}

		#endregion

		public void EnsureCoordinatesValid(FieldCoordinates coordinates)
		{
			if (coordinates.Row < 0)
			{
				coordinates.Row = 0;
			}
			else if (coordinates.Row >= Size)
			{
				coordinates.Row = Size - 1;
			}

			if (coordinates.Column < 0)
			{
				coordinates.Column = 0;
			}
			else if (coordinates.Column >= Size)
			{
				coordinates.Column = Size - 1;
			}
		}

		void InitField()
		{
			field = new bool[Size, Size];
		}

		public virtual void CellClicked(int row, int column)
		{
			if (FieldClicked != null)
			{
				FieldClicked(this, new FieldClickedEventArgs(this, row, column));
			}
			else
			{
				InvertCell(row, column);
			}
		}

		public void InvertCell(int row, int column)
		{
			if ((row < 0 || row >= Size)
				|| (column < 0 || column >= Size))
			{
				return;
			}
			this[row, column] = !this[row, column];
		}

		public void Invert4Neighbors(int row, int column)
		{
			InvertCell(row - 1, column);
			InvertCell(row, column - 1);
			InvertCell(row + 1, column);
			InvertCell(row, column + 1);
		}

		public void Invert5Cross(int row, int column)
		{
			InvertCell(row, column);
			Invert4Neighbors(row, column);
		}

		public IEnumerable<FieldCoordinates> GetBlackCells()
		{
			return Cells().Where(cell => field[cell.Row, cell.Column]);
		}

		public IEnumerable<FieldCoordinates> Cells()
		{
			for (int row = 0; row < Size; row++)
			{
				for (int column = 0; column < Size; column++)
				{
					yield return new FieldCoordinates(row, column);
				}
			}
		}
	}
}
